package service

import (
	"context"
	"mini-app/config/mysql"
	"mini-app/internal/app/grpc/client"
	"mini-app/internal/app/grpc/protoc/sale_adminc"
	"mini-app/internal/app/grpc/protoc/system_admin"
	"mini-app/internal/dal"
	"mini-app/internal/dao"
	"mini-app/internal/models"
	"strings"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/logx"
	"gorm.io/gorm"
)

type GoodsReview struct{}

func (GoodsReview) Create(
	ctx context.Context,
	openid string,
	orderID string,
	star string,
	content string,
	images string,
) (reviewID string, err error) {
	if orderID == "" {
		return "", errorx.New("订单id不能为空", -1)
	}
	detail, _ := dao.Order{}.Detail(ctx, dal.Q, openid, orderID, "", "", "", 0)
	if detail == nil {
		return "", errorx.New("订单不存在", -1)
	}
	if detail.OrderStatus != 12 {
		return "", errorx.New("订单未完成，不能评价", -1)
	}
	if detail.ReviewID != "" {
		return "", errorx.New("不能重复评测", -1)
	}
	confirmImages := []string{}
	if images != "" {
		imageArr := strings.Split(images, ",")
		for _, imgURL := range imageArr {
			SystemAdminClient, clientErr := client.GetSystemAdminClient()
			if clientErr != nil {
				return
			}
			//文件确认
			var req system_admin.ConfirmFileReq
			req.FileUrl = imgURL
			res, err1 := SystemAdminClient.ConfirmFile(context.Background(), &req)
			if err1 != nil && res.Code != 0 {
				logx.Error(context.Background(), "confirm file error", logx.Any("res", res), logx.Any("err", err1.Error()))
				return
			}
			confirmImages = append(confirmImages, res.FileUrl)
		}
	}
	newImages := ""
	if len(confirmImages) > 0 {
		newImages = strings.Join(confirmImages, ",")
	}
	goodsReviewRecord := models.GoodsReview{
		OpenID:  openid,
		OrderID: orderID,
		GoodsID: detail.GoodsID,
		Star:    star,
		Content: content,
		Images:  newImages,
	}
	db := mysql.NewDB()
	err = db.Transaction(func(tx *gorm.DB) error {
		reviewID, err = dao.GoodsReview{}.Create(ctx, tx, goodsReviewRecord)
		if err != nil || reviewID == "" {
			return errorx.New("新增评测失败", -1)
		}
		success := dao.Order{}.SetReviewID(ctx, tx, orderID, reviewID)
		if !success {
			reviewID = ""
			return errorx.New("新增评测失败", -1)
		}
		return nil
	})
	return reviewID, err
}

func (GoodsReview) Update(
	ctx context.Context,
	openid string,
	id string,
	star string,
	content string,
	images string,
) error {
	detail := dao.GoodsReview{}.Detail(ctx, mysql.NewDB(), id)
	if detail == nil {
		return errorx.New("评测不存在", -1)
	}
	if detail.AuditID != "" {
		auditDetail := dao.GoodsReview{}.GetAuditStatus(ctx, mysql.NewDB(), detail.AuditID)
		if auditDetail == nil {
			return errorx.New("数据异常", -1)
		}
		if auditDetail.AuditStatus == 1 {
			return errorx.New("评测已审核通过，不能修改", -1)
		}
	}

	oldImages := strings.Split(detail.Images, ",")
	imagesTemp := images
	newImages := strings.Split(images, ",")
	// 保存新的图片
	SystemAdminClient, clientErr := client.GetSystemAdminClient()
	if clientErr != nil {
		return errorx.New("图片保存失败", -1)
	}
	for _, imageURL := range newImages {
		if !strings.Contains(detail.Images, imageURL) {
			//文件确认
			res, err1 := SystemAdminClient.ConfirmFile(context.Background(), &system_admin.ConfirmFileReq{
				FileUrl: imageURL,
			})
			if err1 != nil && res.Code != 0 {
				logx.Error(context.Background(), "confirm file error", logx.Any("res", res), logx.Any("err", err1.Error()))
				return errorx.New("图片保存失败", -1)
			}
			images = strings.Replace(images, imageURL, res.FileUrl, 1)
		}
	}
	// 删除旧的图片
	for _, imageURL := range oldImages {
		if !strings.Contains(imagesTemp, imageURL) {
			SystemAdminClient.DeleteFile(context.Background(), &system_admin.DeleteFileReq{
				FileUrl: imageURL,
			})
		}
	}

	success := dao.GoodsReview{}.Update(ctx, mysql.NewDB(), openid, id, star, content, images)
	if !success {
		return errorx.New("评测修改失败", -1)
	}
	dao.GoodsReview{}.ResetAuditStatus(ctx, mysql.NewDB(), id)
	return nil
}

func (GoodsReview) List(
	ctx context.Context,
	openid string,
	status int,
	page, limit int,
) ([]dao.GoodsReviewListT, int64, error) {
	records, total := dao.GoodsReview{}.List(
		ctx,
		mysql.NewDB(),
		openid, "",
		0, "", 0, -1,
		status,
		0, 0,
		page, limit,
	)
	saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
	if saleAdminClientErr != nil {
		logx.Error(ctx, "connect sale admin grpc error", logx.Any("saleAdminClientErr", saleAdminClientErr))
		return []dao.GoodsReviewListT{}, 0, errorx.New("获取商品信息失败", -1)
	}
	for index, record := range records {
		rsp, err := saleAdminClient.GoodsDetail(ctx, &sale_adminc.GoodsDetailReq{GoodsId: record.GoodsID})
		if err == nil && rsp.GoodsId != "" {
			records[index].GoodsName = rsp.GoodsName
			records[index].GoodsImage = rsp.GoodsImage
			records[index].ReviewPoints = int(rsp.ReviewPoints)
		}
	}
	if len(records) == 0 {
		records = []dao.GoodsReviewListT{}
	}
	return records, total, nil
}

func (GoodsReview) Detail(
	ctx context.Context,
	reviewID string,
	orderID string,
) (record *dao.GoodsReviewListT, err error) {
	if orderID != "" {
		orderDetail, _ := dao.Order{}.Detail(ctx, dal.Q, "", orderID, "", "", "", 0)
		if orderDetail == nil {
			return nil, errorx.New("订单不存在", -1)
		}
		reviewID = orderDetail.ReviewID
	}
	detail := dao.GoodsReview{}.Detail(ctx, mysql.NewDB(), reviewID)
	if detail == nil {
		return nil, errorx.New("评测不存在", -1)
	}
	saleAdminClient, saleAdminClientErr := client.GetSaleAdminClient()
	if saleAdminClientErr != nil {
		logx.Error(ctx, "connect sale admin grpc error", logx.Any("saleAdminClientErr", saleAdminClientErr))
		return nil, errorx.New("获取商品信息失败", -1)
	}
	rsp, err := saleAdminClient.GoodsDetail(ctx, &sale_adminc.GoodsDetailReq{GoodsId: detail.GoodsID})
	if err == nil && rsp.GoodsId != "" {
		detail.GoodsName = rsp.GoodsName
		detail.GoodsImage = rsp.GoodsImage
	}
	return detail, nil
}

// NearbyReviews 附近评测
func (GoodsReview) NearbyReviews(
	ctx context.Context,
	page, limit int,
) ([]dao.GoodsReviewListT, int64) {
	if page == 0 {
		page = 1
	}
	if limit == 0 {
		limit = 20
	}
	records, total := dao.GoodsReview{}.List(
		ctx,
		mysql.NewDB(),
		"", "",
		0, "", 0, 0,
		1,
		0, 0,
		page, limit)
	for index, record := range records {
		records[index].OrderID = ""
		records[index].GoodsID = ""
		userDetail, _ := dao.User{}.UserInfo(ctx, dal.Q, record.OpenID, "", "")
		if userDetail != nil {
			records[index].WeChatAvatar = userDetail.Image
		}
	}
	if len(records) == 0 {
		records = []dao.GoodsReviewListT{}
	}
	return records, total
}
